SpringCloud Consul 服务注册中心
参考资料 Consul Documentation 参考资料 Spring Cloud Consul 中文文档 参考资料 Spring Cloud Consul 服务注册与发现 参考资料 consul集群——docker-compose.yml
Consul 是什么?
在 Spring Cloud 中,大部分组件都有备选方案,例如服务注册中心,除了常见 Eureka 之外,还有 Zookeeper 和 Consul 等。 Consul 是 HashiCorp 公司推出来的开源产品,主要提供了服务发现、服务隔离、服务配置等功能。
相比于 Eureka 和 Zookeeper ,Consul 配置更加一站式,因为它内置了很多微服务常见的需求,比如:服务发现与注册、分布式一致性协议实现、健康检查、键值对存储、多数据中心等,我们不再需要借助第三方组件来实现这些功能。
配置环境
不同于 Eureka , Consul 使用 Go 语言开发,所以,使用 Consul ,需要先安装 Consul Server ,即服务注册中心。
这里照旧使用 Docker 来配置环境
编写一个 docker-compose.yml
集群环境
version: '3.3'
services:
consul1:
image: consul:latest
container_name: consul1
#restart: always
command: agent -server -client=0.0.0.0 -bootstrap-expect=3 -node=consul1
volumes:
- ./consul1/data:/consul/data
- ./consul1/config:/consul/config
consul2:
image: consul:latest
container_name: consul2
#restart: always
command: agent -server -client=0.0.0.0 -retry-join=consul1 -node=consul2
volumes:
- .consul2/data:/consul/data
- .consul2/config:/consul/config
consul3:
image: consul:latest
container_name: consul3
#restart: always
command: agent -server -client=0.0.0.0 -retry-join=consul1 -node=consul3
volumes:
- ./consul3/data:/consul/data
- ./consul3/config:/consul/config
consul4:
image: consul:latest
container_name: consul4
#restart: always
ports:
- 8500:8500
command: agent -client=0.0.0.0 -retry-join=consul1 -ui -node=client1
volumes:
- ./consul4/data:/consul/data
- ./consul4/config:/consul/config
启动了 4个consul,其中consul1 是主节点,consul2、consul3 是子节点。consul4是提供ui服务的。
# 启动服务
docker-compose up -d
访问地址: http://localhost:8500 来查看集群信息
server 和 client 模式
server 模式和 client模式 都是 consul节点的类型(client 不是指用户客户端)
server 模式提供数据持久化功能。
client 模式不提供持久化功能,并且实际上他也不工作,只是把用户客户端的请求转发到 server 模式的节点。所以可以把 client 模式的节点想象成 LB(load balance),只负责请求转发。
通常 server 模式的节点需要配置成多个例如3个,5个。而 client 模式节点个数没有限制。
server 模式启动参数
# 表示当前使用的 server模式;如果没有指定,则表示是 client模式。
-server
# 指定当前节点在集群中的名称。
-node
# 指定配置文件路径,定义服务的;路径下面的所有.json结尾的文件都被访问;缺省值为:/consul/config。
-config-dir
# consul 存储数据的目录;缺省值为:/consul/data
-data-dir
# 数据中心名称,缺省值为 dc1
-datacenter
# 使用 consul 自带的 web UI界面 。
-ui
# 加入到已有的集群中。
-join
# 检查服务是否处于活动状态,类似开启心跳。
-enable-script-checks
# 绑定服务器的 ip 地址。
-bind
# 客户端可访问ip,缺省值为:“127.0.0.1”,即仅允许环回连接。
-client
# 在一个 datacenter 中期望的 server节点数目,consul启动时会一直等待直到达到这个数目的server才会引导整个集群。
# 这个参数的值在同一个datacenter的所有server节点上必须保持一致。
-bootstrap-expect
另外一个参数 -bootstrap
,用来控制一个 server 是否运行在 bootstrap 模式:
当一个 server 处于 bootstrap 模式时,它可以选举自己为 leader;注意在一个 datacenter 中只能有一个 server 处于 bootstrap 模式。
所以这个参数一般只能用在只有一个 server 的开发环境中,在有多个 server 的 cluster产品环境中,不能使用这个参数,否则如果多个 server都标记自己为 leader那么会导致数据不一致。另外该标记不能和 -bootstrap-expect
同时指定。
导入依赖
<!--springcloud consul-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 这里最好加上这个状态检查 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置服务生产者
# consul 服务端口号
server:
port: 8006
spring:
application:
name: provider-payment
# consul 注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
# hostname: 127.0.0.1
service-name: ${spring.application.name}
# healthCheckPath: /actuator/health # 可以手动设置检查路径
healthCheckInterval: 15s
prefer-ip-address: true # 注册过程使用 IP 而不是主机名,这个一定要开启!
# hostname: 169.254.212.146:8006 #或者使用这个把 hostname 改成 IP 地址
# 开启状态检查
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
编写一个 Controller
@RestController
@Slf4j
public class PaymentController {
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/payment/consul")
public String paymentConsul(){
return "spring cloud with consul:"+serverPort+"\t"+ UUID.randomUUID().toString();
}
}
最后别忘了在启动类加上 @EnableDiscoveryClient
注解
启动后就能在 UI 面板看到这个注册的服务了(如果没有配置上面那个健康检查,就会出现这个红叉)
配置好的是这样的
配置服务消费者
# consul服务端口号
server:
port: 8080
spring:
application:
name: consumer-order
# consul服务注册中心
cloud:
consul:
host: localhost
port: 8500
discovery:
# hostname: 127.0.0.1
service-name: ${spring.application.name}
prefer-ip-address: true # 注册过程使用 IP 而不是主机名
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
启动类
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerConsulOrder8080Application {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerConsulOrder8080Application.class, args);
}
}
创建一个 Controller 测试
@RestController
@Slf4j
public class OrderConsulController {
public static final String INVOKE_URL = "http://provider-payment";
@Resource
private RestTemplate restTemplate;
@GetMapping(value = "/consumer/payment/consul")
public String paymentInfo(){
return restTemplate.getForObject(INVOKE_URL+"/payment/consul",String.class);
}
}
访问测试
http://localhost:8080/consumer/payment/consul
检查一下 Consul 当前已经有两个服务了